<template>
  <!-- 搜索框  -->
  <el-card>
    <el-form :inline="true" class="form">
      <el-form-item label="菜单名称">
        <el-input @keyup.enter="search" placeholder="请你输入搜索菜单名称"
                  v-model="pageRequest.menuName"></el-input>
      </el-form-item>
      <el-form-item style="width: 200px" label="菜单状态">
        <el-select
            v-model="pageRequest.status"
            placeholder="请选择状态"
            clearable>
          <el-option label="启用" :value="0"></el-option>
          <el-option label="禁用" :value="1"></el-option>
          <el-option label="隐藏" :value="2"></el-option>
        </el-select>
      </el-form-item>
      <el-form-item style="width: 200px" label="链接方式">
        <el-select
            v-model="pageRequest.frame"
            placeholder="请选择链接方式"
            clearable>
          <el-option label="普通" :value="0"></el-option>
          <el-option label="跳转" :value="1"></el-option>
          <el-option label="内嵌" :value="2"></el-option>
        </el-select>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" size="default" @click="search">
          搜索
        </el-button>
        <el-button type="primary" size="default" @click="reset">重置</el-button>
      </el-form-item>
    </el-form>
  </el-card>
  <el-card style="margin: 10px 0px;">
    <el-button icon="Plus" type="primary" plain size="default" v-hasPermi="['menu_add']" @click="handleAdd(0)">新增
    </el-button>
    <el-button icon="Sort" type="success" plain size="default" @click="expandAll">{{ !isExpandAll ? '展开' : '折叠' }}
    </el-button>
    <el-table ref="tableRef" :data="PermisstionArr" style="width: 100%; margin: 10px 0;"
              :default-expand-all="isExpandAll" row-key="id"
              border>
      <el-table-column align="center" label="菜单名称"
                       prop="menuName"></el-table-column>
      <el-table-column align="center" width="80" label="菜单类型" prop="type">
        <template #default="scope">
          <!-- 根据不同的状态显示不同的颜色或类型 -->
          <el-tag v-if="scope.row.type === 'M'" type="primary">目录</el-tag>
          <el-tag v-if="scope.row.type === 'C'" type="success">菜单</el-tag>
          <el-tag v-if="scope.row.type === 'F'" type="warning">权限</el-tag>
        </template>
      </el-table-column>
      <el-table-column align="center" width="60" label="排序" prop="orderNum"></el-table-column>
      <el-table-column align="center" width="60" label="图标" prop="icon">
        <template #default="scope">
          <div style="display: flex; justify-content: center;">
            <el-icon :size="16">
              <component :is="scope.row.icon" />
            </el-icon>
          </div>
        </template>
      </el-table-column>
      <el-table-column align="center" label="权限标识" prop="permissionVal"></el-table-column>
      <el-table-column align="center" width="80" label="链接方式" prop="frame">
        <template #default="scope">
          <el-tag v-if="scope.row.frame === 0" type="success">普通</el-tag>
          <el-tag v-if="scope.row.frame === 1" type="warning">跳转</el-tag>
          <el-tag v-if="scope.row.frame === 2" >内嵌</el-tag>
        </template>
      </el-table-column>
      <el-table-column align="center" label="路由地址" prop="path"></el-table-column>
      <el-table-column align="center" label="组件路径" prop="component"></el-table-column>
      <el-table-column align="center" width="80" label="菜单状态" prop="status">
        <template #default="scope">
          <!-- 根据不同的状态显示不同的颜色或类型 -->
          <el-tag v-if="scope.row.status === 1" type="danger">停用</el-tag>
          <el-tag v-if="scope.row.status === 0" type="success">启用</el-tag>
          <el-tag v-if="scope.row.status === 2" type="warning">隐藏</el-tag>
        </template>
      </el-table-column>
      <el-table-column align="center" width="300px" label="操作">
        <template #default="scope">
          <el-button
              type="primary"
              v-hasPermi="['menu_add']"
              icon="Plus"
              size="small"
              @click="handleAdd(scope.row.id)"
          >
            添加
          </el-button>
          <el-button
              type="primary"
              v-hasPermi="['menu_update']"
              icon="Edit"
              size="small"
              @click="handleUpdate(scope.row)"
          >
            修改
          </el-button>
          <el-popconfirm :title="`你确定要删除${scope.row.menuName}?`" width="260px"
                         @confirm="removeMenu(scope.row.id)">
            <template #reference>
              <el-button v-hasPermi="['menu_delete']"
                         icon="Delete" type="primary" size="small">删除
              </el-button>
            </template>
          </el-popconfirm>
        </template>
        <!-- row:即为已有的菜单对象|按钮的对象的数据 -->
      </el-table-column>
    </el-table>
  </el-card>
  <!-- 对话框组件:添加或者更新已有的菜单的数据结构 -->
  <el-drawer v-model="dialogVisible" :title="menuData.id ? '更新菜单' : '添加菜单'">
    <!-- 表单组件:收集新增与已有的菜单的数据 -->
    <el-form :rules="rules" ref="form" :model="menuData" label-width="120px">
      <el-row>
        <el-col :span="24">
          <el-form-item style="width: 300px" label="上级菜单">
            <el-tree-select
                v-model="menuData.parentId"
                :data="menuOptions"
                :props="{ value: 'id', label: 'menuName', children: 'children' }"
                value-key="menuId"
                placeholder="选择上级菜单"
                check-strictly
            />
          </el-form-item>
        </el-col>
        <el-col :span="24">
          <el-form-item style="width: 400px" label="菜单类型" prop="type">
            <el-radio-group v-model="menuData.type">
              <el-radio label="M">目录</el-radio>
              <el-radio label="C">菜单</el-radio>
              <el-radio label="F">权限</el-radio>
            </el-radio-group>
          </el-form-item>
        </el-col>
        <el-col :span="24" v-if="menuData.type != 'F'">
          <el-form-item style="width: 300px" label="菜单图标" prop="icon">
            <el-popover
                v-model:visible="showChooseIcon"
                placement="bottom-start"
                :width="540"
                trigger="manual"
                @show="showSelectIcon"
            >
              <template #reference>
                <el-input v-model="menuData.icon"
                          placeholder="点击选择图标"
                          @click="showSelectIcon"
                          readonly>
                  <template #prefix>
                    <el-icon v-if="menuData.icon" :size="16">
                      <component :is="menuData.icon" />
                    </el-icon>
                    <el-icon v-else style="height: 32px;width: 16px;">
                      <search/>
                    </el-icon>
                  </template>
                </el-input>
              </template>
              <icon-select ref="iconSelectRef"
                           :active-icon="menuData.icon"
                           @selected="selected"
              />
            </el-popover>
          </el-form-item>
        </el-col>
        <el-col :span="24">
          <el-form-item style="width: 300px" label="菜单名称" prop="menuName">
            <el-input v-model="menuData.menuName" placeholder="请输入菜单名称"/>
          </el-form-item>
        </el-col>
        <el-col :span="24" v-if="menuData.type !== 'F'">
          <el-form-item label="外链">
            <template #label>
                        <span>
                           <el-tooltip content="访问的路由地址，是否为外部地址"
                                       placement="top">
                              <el-icon><question-filled/></el-icon>
                           </el-tooltip>
                           链接方式
                        </span>
            </template>
            <el-radio-group v-model="menuData.frame">
              <el-radio :label="0">普通</el-radio>
              <el-radio :label="1">跳转</el-radio>
              <el-radio :label="2" v-if="menuData.type === 'C'">内嵌</el-radio>
            </el-radio-group>
          </el-form-item>
        </el-col>
        <el-col :span="24">
          <el-form-item label="菜单状态" prop="status">
            <el-radio-group v-model="menuData.status">
              <el-radio :label="0">正常</el-radio>
              <el-radio :label="1">停用</el-radio>
              <el-radio :label="2" v-if="menuData.type === 'C'">隐藏</el-radio>
            </el-radio-group>
          </el-form-item>
        </el-col>
        <el-col :span="24">
          <el-form-item label="显示排序" prop="orderNum">
            <el-input-number v-model="menuData.orderNum" controls-position="right" :min="0"/>
          </el-form-item>
        </el-col>
        <el-col :span="24" v-if="menuData.type !== 'F'">
          <el-form-item style="width: 300px" prop="path">
            <template #label>
                        <span>
                           <el-tooltip content="访问的路由地址，如：`user`"
                                       placement="top">
                              <el-icon><question-filled/></el-icon>
                           </el-tooltip>
                           路由地址
                        </span>
            </template>
            <el-input v-model="menuData.path" placeholder="请输入路由地址"/>
          </el-form-item>
        </el-col>
        <el-col :span="24" v-if="menuData.type !== 'F'">
          <el-form-item style="width: 300px" prop="component">
            <template #label>
                        <span v-if="menuData.type === 'M'">
                           <el-tooltip content="重定向路由，指向二级菜单，如：`user`，如配置了链接方式则以`http(s)://`开头"
                                       placement="top">
                              <el-icon><question-filled/></el-icon>
                           </el-tooltip>
                           重定向路由
                        </span>
              <span v-else>
                           <el-tooltip content="访问的组件路径，如：`system/user/index`，默认在`views`目录下，如配置了链接方式则以`http(s)://`开头"
                                       placement="top">
                              <el-icon><question-filled/></el-icon>
                           </el-tooltip>
                           组件路径
                        </span>
            </template>
            <el-input v-model="menuData.component" placeholder="请输入组件路径"/>
          </el-form-item>
        </el-col>
        <el-col :span="24" v-if="menuData.type === 'F'">
          <el-form-item style="width: 300px" prop="permissionVal">
            <el-input v-model="menuData.permissionVal" placeholder="请输入权限标识" maxlength="100"/>
            <template #label>
                        <span>
                           <el-tooltip
                               content="控制器中定义的权限字符，如：@PreAuthorize(`@ss.hasPermi('system:user:list')`)"
                               placement="top">
                              <el-icon><question-filled/></el-icon>
                           </el-tooltip>
                           权限字符
                        </span>
            </template>
          </el-form-item>
        </el-col>
      </el-row>
    </el-form>

    <template #footer>
            <span class="dialog-footer">
                <el-button @click="dialogVisible = false">取消</el-button>
                <el-button type="primary" @click="save">
                    确定
                </el-button>
            </span>
    </template>
  </el-drawer>
</template>

<script setup name="Menu">
import {ref, onMounted, nextTick} from "vue";
import {reqAllPermisstion, reqAddOrUpdateMenu, reqRemoveMenu} from '@/api/system/menu';
import IconSelect from "@/components/IconSelect";
import {ClickOutside as vClickOutside, ElMessage} from 'element-plus'
import setting from "@/setting.js";
import useLayOutSettingStore from '@/store/modules/setting';

let settingStore = useLayOutSettingStore();
//获取form组件实例
const form = ref();
//是否展开
let isExpandAll = ref(false);
//搜索按钮的回调
const search = () => {
  //再次发请求根据关键字
  getHasPermisstion();
  //keyword.value = '';
}
//分页查询请求参数
let pageRequest = ref({
  menuName: '',
  status: '',
  frame: '',
});

// 获取表格实例
let tableRef = ref();
const showChooseIcon = ref(false)
const iconSelectRef = ref(null)
//存储菜单的数据
const PermisstionArr = ref([]);
//下拉菜单数据
const menuOptions = ref([]);
//控制对话框的显示与隐藏
const dialogVisible = ref(false);
//携带的参数
const menuData = ref({
  permissionVal: "",
  menuName: "",
  orderNum: 0,
  path: "",
  component: "",
  type: "",
  icon: "",
  parentId: 0,
  status: 0,
  frame: 0,
})
//获取菜单数据的方法
const getHasPermisstion = async () => {
  let result = await reqAllPermisstion(pageRequest.value);
  if (result.code == setting.SYSTEM_SUCCESS) {
    PermisstionArr.value = result.data;
    //制空
    menuOptions.value = []
    const menu = {id: 0, menuName: "主类目", children: []};
    menu.children = result.data;
    menuOptions.value.push(menu);
  }
}
//展开菜单
const expandAll = () => {
  isExpandAll.value = !isExpandAll.value;  // 切换展开/折叠状态
  if (tableRef.value) {
   const expandRows = (rows) => {
    rows.forEach((row) => {
      // 确保 row 为正确的数据项，并且表格引用存在
      tableRef.value.toggleRowExpansion(row, isExpandAll.value);
      if(row.children && row.children.length > 0) {
        expandRows(row.children)
      }
    });
   }
   expandRows(PermisstionArr.value)
  }
};

//添加菜单按钮的回调
const handleAdd = (id) => {
  //清空数据
  Object.assign(menuData.value, {
    permissionVal: "",
    menuName: "",
    orderNum: 0,
    path: "",
    component: "",
    type: "M",
    icon: "",
    status: 0,
    id: "",
  })
  //对话框显示出来
  dialogVisible.value = true;
  menuData.value.parentId = (id);
  //清除上一次的错误的提示信息
  nextTick(() => {
    form.value.clearValidate('menuName');
  });
}

//编辑已有的菜单
const handleUpdate = (row) => {
  dialogVisible.value = true;
  //点击修改按钮:收集已有的菜单的数据进行更新
  Object.assign(menuData.value, row);
  //清除上一次的错误的提示信息
  nextTick(() => {
    form.value.clearValidate('menuName');
  });
}

/** 展示下拉图标 */
const showSelectIcon = () => {
  iconSelectRef.value.reset()
  showChooseIcon.value = true;
}
/** 选择图标 */
const selected = (name) => {
  menuData.value.icon = name;
  showChooseIcon.value = false;
}

//确定按钮的回调
const save = async () => {
  //表单校验结果,结果通过在发请求、结果没有通过不应该在发生请求
  await form.value.validate();
  //发请求:新增子菜单|更新某一个已有的菜单的数据
  let result = await reqAddOrUpdateMenu(menuData.value);
  if (result.code == setting.SYSTEM_SUCCESS) {
    //对话框隐藏
    dialogVisible.value = false;
    //提示信息
    ElMessage({type: 'success', message: menuData.value.id ? '更新成功' : '添加成功'})
    //再次获取全部最新的菜单的数据
    getHasPermisstion();
  }
}

//删除按钮回调
const removeMenu = async (id) => {
  let result = await reqRemoveMenu(id);
  if (result.code == setting.SYSTEM_SUCCESS) {
    ElMessage({type: 'success', message: '删除成功'});
    getHasPermisstion();

  }
}

//重置按钮的回调
const reset = () => {
  settingStore.refsh = !settingStore.refsh;
}

const rules = {
  menuName: [{required: true, message: "菜单名称不能为空", trigger: "blur"}],
  orderNum: [{required: true, message: "菜单顺序不能为空", trigger: "blur"}],
  path: [{required: true, message: "路由地址不能为空", trigger: "blur"}],
  // permissionVal: [{required: true, message: "权限字符不能为空", trigger: "blur"}],
  // component: [{required: true, message: "组件路径不能为空", trigger: "blur"}]
}
//组件挂载完毕
onMounted(() => {
  getHasPermisstion();
});
</script>

<style scoped>
.form {
  margin-top: 15px;
  display: flex;
  align-items: center;
}
</style>
